local cjson = require("cjson")

local client_sdk = require("JGE_RS_SDK")

-- 初始化sdk配置------------------------------
local sdk_config = {
    -- 发送到SDK的数据自动转码gbk到utf8(客户端是GBK编码开启)
    send_to_utf8 = true,
    -- SDK返回的数据自动转码utf8到gbk (客户端是GBK编码开启)
    receive_to_gbk = true,
    -- 密钥(必须32位) 通讯加密/更新加密
    psk = "THIS_IS_A_32_BYTE_FIXED_PSK!!!!!",
    -- 客户端类型 对应静态资源目录前缀 staic/update/{client_type}/xx
    client_type = "pc",
    -- 服务端tcp地址
    tcp_address = "127.0.0.1:8083",
    -- 服务端http地址
    http_address = "http://127.0.0.1:8080",
    -- 获取更新包的http地址/允许放在其他静态资源存储上
    update_address = "http://127.0.0.1:8080",
}
client_sdk.init_config(sdk_config)
----------------------------------------------


local JGESDK = class()

local update_flag = false;

local update_runing = false;

function deepCopyFilterUserdata(orig)
	if type(orig) == "userdata" then
	     return nil  -- 直接剔除 userdata
	elseif type(orig) ~= "table" then
	     return orig  -- 非 table 类型直接返回
	end

	local copy = {}
	for k, v in pairs(orig) do
	    -- 递归处理键和值，确保嵌套结构中的 userdata 也被过滤
	    local key = deepCopyFilterUserdata(k)
	    local value = deepCopyFilterUserdata(v)
	    if key ~= nil and value ~= nil then
	        copy[key] = value
	     end
	end
	return copy
end

-- 获取SDK事件 数量(每帧最多处理几条事件 太多会阻塞主线程 默认一帧处理一条)
function JGESDK:处理事件(数量)
    if 数量 == nil then
        数量 = 1
    end
	for i=1,数量 do
        local event = client_sdk.poll_event() -- 获取事件
        if event == nil then break end
        -- 解析事件数据
        local event_type = event.event_type
        local data = event.event_data
        if event_type == client_sdk.EVENT_CONNECTED then -- 与服务端建立连接
            tp.提示:写入("#Y/连接服务器成功！")
        elseif event_type == client_sdk.EVENT_DISCONNECTED then -- 与服务端连接断开
            self:调试输出("连接断开")
            self:连接断开处理()
        elseif event_type == client_sdk.EVENT_MESSAGE then -- 接收到服务端消息
            self:消息处理(data)
        elseif event_type == client_sdk.EVENT_ERROR then  -- SDK报错消息
            tp.提示:写入("#R"..data)
        elseif event_type == client_sdk.EVENT_UPDATE_STARTED then  -- 更新开始
            tp.提示:写入("#开始更新")
            update_runing = true
        elseif event_type == client_sdk.EVENT_UPDATE_PROGRESS then -- 更新进度
            self:更新进度(data)
        elseif event_type == client_sdk.EVENT_UPDATE_COMPLETED then -- 更新完成
            tp.提示:写入("更新完成:"..data)
            update_flag = true
            update_runing = false
        elseif event_type == client_sdk.EVENT_UPDATE_FAILED then -- 更新失败
            tp.提示:写入("更新失败:"..data)
            update_runing = false
        elseif event_type == client_sdk.EVENT_HOT_UPDATE_DATA then -- 热更数据
            self:热更新处理(data)
        elseif event_type == client_sdk.EVENT_HOT_UPDATE_COMPLETED then -- 热更完成
            tp.提示:写入("热更完成")
        elseif event_type == client_sdk.EVENT_HOT_UPDATE_FAILED then -- 热更失败
            tp.提示:写入("热更失败:"..data)
        end
        -- 及时清理内存
        event_type = nil
        data = nil
        event = nil
	end
end

function JGESDK:版本信息()
    return client_sdk.get_current_version();
end

function JGESDK:更新进度(data)
    local ok, decode_data = pcall(cjson.decode, data)
    if ok then
        if decode_data.type == 1 then
            tp.提示:写入("开始下载更新包 "..decode_data.package.." 大小:"..(decode_data.total_size/1000).."kb")
        end
        if decode_data.type == 2 then
            tp.提示:写入("下载更新包 "..decode_data.package.." 进度:"..decode_data.progress.."%")
        end
    end
end

-- 处理客户端接收到的事件
local 数据交换 = require("script/网络/数据交换")()
function JGESDK:消息处理(data)
    if #data < 2 then return end
    local ok, decode_data = pcall(cjson.decode, data)
    if ok then
        local 数据 = {
            序号 = tonumber(decode_data.message_type),
            内容 = decode_data.message_data and deepCopyFilterUserdata(decode_data.message_data) or 1
        }
        数据交换:数据到达(数据)
    else
        self:调试输出("解析消息失败:"..data)
    end
end

-- 向服务端发送数据 规范固定格式
function JGESDK:发送(序号, 内容)
    if not 序号 then return end
    local json = {
        message_type = 序号,
        message_data = 内容 or 1
    }
    local json_str = cjson.encode(json)
    client_sdk.send_message(json_str)
end

-- 与服务端连接
function JGESDK:连接处理(ip, 端口)

    -- 如果重新指定改了ip和端口则使用指定的地址
    if ip ~= nil and 端口 ~= nil then
        sdk_config.tcp_address = ip..":"..端口
        client_sdk.init_config(sdk_config)
    end

    if update_flag == false and update_runing == false then
        -- 下载更新包
        tp.提示:写入("#Y开始检测更新...请耐心等待..")
        client_sdk.start_auto_update()
        return
    end

    if update_runing == true then
        tp.提示:写入("#Y更新正在进行中...请耐心等待..")
        return
    end

    if client_sdk.is_connected() == false then
        -- 发起连接
        local res = client_sdk.connect_to_server()
    end
end

-- 与服务端连接断开后的处理
function JGESDK:连接断开处理()
    -- 直接尝试重连
    self:连接处理()
end

-- 主动与服务端断开连接
function JGESDK:断开连接()
    client_sdk.disconnect()
end

-- 输出调试日志并保存到本地文件 JGE_DEBUG.log
function JGESDK:调试输出(data)
    client_sdk.print_debug(data)
end

function JGESDK:同步热更()
    client_sdk.start_hot_update()
end

function JGESDK:加载热更()
    -- 发起热更
    client_sdk.start_hot_update()
    -- 接收热更数据
    local event_type = nil
    -- 接收所有热更数据
    repeat
        local event = client_sdk.poll_event() -- 获取事件
        if event ~= nil then 
            event_type = event.event_type
            local data = event.event_data
            if event_type == client_sdk.EVENT_HOT_UPDATE_DATA then
                self:热更新处理(data)
            end
        end
    until event_type ~= nil and event_type ~= client_sdk.EVENT_HOT_UPDATE_DATA
end

function JGESDK:热更新处理(hot_data)
    if hot_data ~= nil and hot_data ~= "" then
        local ok, decode_hot_data = pcall(cjson.decode, hot_data)
        -- tp.提示:写入("#G热更新文件: "..decode_hot_data.path)

        if ok then
            self:调试输出(decode_hot_data.path)
            -- 数据
            if decode_hot_data.file_type == 1 then
                if type(decode_hot_data.context) == "string" then
                    local ok, decode_json = pcall(cjson.decode, decode_hot_data.context)
                    if ok then
                        _JGE_HOT_UPDATE[decode_hot_data.path] = decode_json
                    else
                        self:调试输出("解析json数据失败" .. decode_hot_data.path)
                    end
                else
                    _JGE_HOT_UPDATE[decode_hot_data.path] = decode_hot_data.context
                end
            end
            -- 脚本
            if decode_hot_data.file_type == 2 then
                local ok, lua_fn = pcall(load(decode_hot_data.context))
                if ok then
                    _JGE_HOT_UPDATE[decode_hot_data.path] = lua_fn
                else
                    self:调试输出("加载lua脚本失败" .. lua_fn)
                end
            end
            decode_hot_data = nil
        else
            self:调试输出("解析热更新数据失败，")
        end
        hot_data = nil
        decode_hot_data = nil
    end
end

return JGESDK

